package zone.czh.woi.woim.client.initializer;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.AllArgsConstructor;
import lombok.Data;
import zone.czh.woi.woim.base.channel.adapter.ProtocolAdapter;
import zone.czh.woi.woim.base.channel.codec.PacketHandler;
import zone.czh.woi.woim.base.channel.codec.PayloadEncoder;
import zone.czh.woi.woim.base.channel.codec.PayloadHandler;
import zone.czh.woi.woim.base.channel.constant.ChannelHandlerName;
import zone.czh.woi.woim.base.constant.WOIMConfig;
import zone.czh.woi.woim.base.obj.vo.Packet;
import zone.czh.woi.woim.client.WOIMClient;
import zone.czh.woi.woim.client.handler.*;
import zone.czh.woi.woim.client.prtocol.builder.ClientProtocolBuilder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
*@ClassName: ClientChannelInitializer
*@Description: None
*@author woi
*/
@Data
@AllArgsConstructor
public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {

    WOIMClient client;

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        //===connection
        pipeline.addLast(ChannelHandlerName.IDLE_STATE_HANDLER,new IdleStateHandler(0, WOIMConfig.WRITER_IDLE_TIME_SECONDS,0));
        pipeline.addLast(ChannelHandlerName.CONNECTION_STATE_HANDLER,new ConnectionStateHandler());
        //===



        pipeline.addLast(ChannelHandlerName.PAYLOAD_HANDLER,new PayloadHandler());
        //===packet handler
        pipeline.addLast(new PayloadInboundHandler(client));
        pipeline.addLast(new PrivateMsgHandler(client.getEventListener()));
        pipeline.addLast(new GroupMsgHandler(client.getEventListener()));
        pipeline.addLast(client.getIntentHandler());
        //===

        //===payload encoder
        PayloadEncoder payloadEncoder = new PayloadEncoder();
        ProtocolAdapter protocolAdapter = client.getConfigurator().getProtocolAdapter();
        Map<String,ProtocolAdapter> adapters = new HashMap<>();
        adapters.put(protocolAdapter.getProtocolName(),protocolAdapter);
        payloadEncoder.setAdapters(adapters);
        payloadEncoder.setProtocolSelector((ctx, payload) -> protocolAdapter.getProtocolName());
        pipeline.addLast(ChannelHandlerName.PAYLOAD_ENCODER,payloadEncoder);
        //===

        //===req handler
        pipeline.addLast(new ReqHandler(client));
        //===

        //===build protocol
        ClientProtocolBuilder clientProtocolBuilder = new ClientProtocolBuilder();
        clientProtocolBuilder.setProtocolAdapters(adapters);
        clientProtocolBuilder.build(pipeline,protocolAdapter.getProtocolName());
        //===

        List<PacketHandler> customHandlers = client.getConfigurator().getCustomHandler();
        if (customHandlers!=null){
            for (MessageToMessageDecoder<Packet> customHandler:customHandlers){
                pipeline.addLast(customHandler);
            }
        }
    }
}
